package com.scs.application.core.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.SimpleTimeZone;

/**
 * 日期时间工具类
 */
@SuppressWarnings("deprecation")
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
    public final static String DEFAULT_PATTER = "yyyy-MM-dd HH:mm:ss";
    public final static String DEFAULT_PATTER_ALL = "yyyy-MM-dd HH:mm:ss.SSS";
    public final static String DEFAULT_PATTER_YMD = "yyyy-MM-dd";
    public final static String YYYYMMDDHHMMSS_PATTER2 = "yyyy-MM-dd HH:mm:ss";


    public final static String YYYYMMDDHHMMSS_PATTER = "yyyyMMddHHmmss";
    /**
     * 仅显示年月日，例如 2021-08-11.
     */
    public static final String DATE_PATTERN = "yyyy-MM-dd";

    public final static String[] parsePatterns = {
            "yyyy-MM-dd HH:mm:ss.SSS",
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM-dd", "yyyy-MM",
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM/dd", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM.dd", "yyyy.MM"};

    public static Date now() {
        return Calendar.getInstance().getTime();
    }

    /**
     * 获取指定日期当周星期一的时间
     *
     * @param date
     * @return
     */
    public static Date getFirstDayOfWeek(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        //获取本周第一天
        calendar.set(Calendar.WEEK_OF_YEAR, calendar.get(Calendar.WEEK_OF_YEAR));
        int dayOfWeek = 0;
        if (calendar.get(Calendar.DAY_OF_WEEK) == 1) {
            dayOfWeek = -6;
        } else {
            dayOfWeek = 2 - calendar.get(Calendar.DAY_OF_WEEK);
        }
        calendar.add(Calendar.DAY_OF_WEEK, dayOfWeek);

        return calendar.getTime();
    }

    /**
     * @Description：  返回 yyyy-MM-dd HH:mm:ss
     */
    public static String nowDate(String fmt) {
        return getDate(new Date(),fmt);
    }

    /**
     * 将日期字符串转换为日期类型
     *
     * @param pattern 日期字符串格式 不传则为 yyyy-MM-dd
     * @return
     * @throws ParseException
     */
    public static Date nowDate2(String pattern){
        if (StringUtils.isBlank(pattern)) pattern = "yyyy-MM-dd";
        SimpleDateFormat df = new SimpleDateFormat(pattern);//设置日期格式
        try {
            return df.parse(df.format(new Date()));
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * @Description：获取当前日期  yyyy-MM-dd HH:mm:ss
     * @Author wyt
     * @Date 2020/8/21
     */
    public static String getDate(Date date,String fmt){
        SimpleDateFormat sdf = new SimpleDateFormat(fmt);
        return sdf.format(date);
    }

    /**
     * 获取指定日期当周星期日的时间
     *
     * @param date
     * @return
     */
    public static Date getLastDayOfWeek(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.setTime(date);
        // Sunday
        calendar.set(Calendar.DAY_OF_WEEK, calendar.getFirstDayOfWeek() + 6);

        return calendar.getTime();
    }

    /**
     * 获取指定日期当月第一天的时间
     *
     * @param date
     * @return
     */
    public static Date getFirstDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        return calendar.getTime();
    }

    /**
     * 获取指定日期当月最后一天的时间
     *
     * @param date
     * @return
     */
    public static Date getLastDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        return calendar.getTime();
    }

    /**
     * 获取指定日期当年第一天的时间
     *
     * @param date
     * @return
     */
    public static Date getFirstDayOfYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, date.getYear() + 1900);
        return calendar.getTime();
    }

    /**
     * 获取指定日期当年最后一天的时间
     *
     * @param date
     * @return
     */
    public static Date getLastDayOfYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, date.getYear() + 1900);
        calendar.roll(Calendar.DAY_OF_YEAR, -1);
        return calendar.getTime();
    }


    /**
     * 获取两个日期相隔的天数
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static float getDateDiffOfDays(Date startDate, Date endDate) {
        long diff = endDate.getTime() - startDate.getTime();

        return diff / (24 * 60 * 60 * 1000);
    }

    /**
     * 获取每天工作小时数。例如：早上9点上班，下午6点下班，休息一个小时，工作时间为8
     *
     * @param startTime 开始时间，格式：HHmm。例如早上7点半，使用0730表示
     * @param endTime   结束时间，格式：HHmm。例如下午6点半，使用1830表示
     * @param restHours 休息时间
     * @return
     */
    public static float getWorkHours(String startTime, String endTime, float restHours) {
        Date m = new Date();
        m.setHours(Integer.parseInt(startTime.substring(0, 2)) - 1);
        m.setMinutes(Integer.parseInt(startTime.substring(2)));
        Date a = new Date();
        a.setHours(Integer.parseInt(endTime.substring(0, 2)) - 1);
        a.setMinutes(Integer.parseInt(endTime.substring(2)));

        return (a.getTime() - m.getTime()) / (1000 * 60 * 60 * 1.0f) - restHours;
    }

    /**
     * 将日期字符串转换为日期类型
     *
     * @param dateStr 日期字符串
     * @param pattern 日期字符串格式
     * @return
     * @throws ParseException
     */
    public static Date parse(String dateStr, String pattern) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
        return dateFormat.parse(dateStr);
    }

    /**
     * 日期型字符串转化为日期 格式
     * { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm",
     * "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm",
     * "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm" }
     */
    public static Date parse(String str) {
        if (str == null) {
            return null;
        }
        try {
            return parseDate(str, parsePatterns);
        } catch (ParseException e) {
            return null;
        }
    }

    public static String formatToAnotherPattern(String dateStr, String pattern, String anotherPatter) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);

        Date date = dateFormat.parse(dateStr);
        dateFormat = new SimpleDateFormat(anotherPatter);
        return dateFormat.format(date);
    }

    public static String format(Date date, String pattern) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
        return dateFormat.format(date);
    }

    public static Date addHours(Date date, int amount) {
        return add(date, Calendar.HOUR_OF_DAY, amount);
    }

    public static Date addDays(Date date, int amount) {
        return add(date, Calendar.DAY_OF_MONTH, amount);
    }


    private static Date add(Date date, int calendarField, int amount) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(calendarField, amount);
        return c.getTime();
    }

    /**
     * 将毫秒格式化，如果大于60秒，返回 1分xx秒，大于60分钟，返回 1小时xx分xx秒
     *
     * @param ms 毫秒
     * @return
     */
    public static String formatTime(long ms) {
        // 小于60秒，以秒显示
        if (ms / 1000 < 60) {
            return ms / 1000 + "秒";
        }

        // 小于60分，以分显示
        if (ms / 1000 / 60 < 60) {
            return ms / 1000 / 60 + "分" + (ms / 1000 % 60) + "秒";
        }

        // 小于24小时
        if (ms / 1000 / 60 / 60 < 24) {
            return (ms / 1000 / 60 / 60) + "时" + (ms / 1000 % 60) + "分" + (ms / 1000 / 60 % 60) + "秒";
        }

        return "";
    }

    public static Date dateToISODate(Date date){
        //T代表后面跟着时间，Z代表UTC统一时间
        SimpleDateFormat format =
                new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        format.setCalendar(new GregorianCalendar(new SimpleTimeZone(0, "GMT")));
        String isoDate = format.format(date);
        try {
            return format.parse(isoDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String localDateTimeToString(LocalDateTime localDateTime){
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        return fmt.format(localDateTime);
    }

    public static int diffDate(Date date1,Date date2)
    {
        int days = (int) ((date2.getTime() - date1.getTime()) / (1000*3600*24));
        return days;
    }

    /**
     * @Description： 判断是否是合法日期格式
     * @Author wyt
     * @Date 2021/2/24
     */
    public static boolean isValidDate(String str) {
        boolean convertSuccess=true;
        // 指定日期格式为四位年/两位月份/两位日期，注意yyyy/MM/dd区分大小写；
        SimpleDateFormat format = new SimpleDateFormat(DEFAULT_PATTER_YMD);
        try {
            // 设置lenient为false. 否则SimpleDateFormat会比较宽松地验证日期，比如2007/02/29会被接受，并转换成2007/03/01
            format.setLenient(false);
            format.parse(str);
        } catch (ParseException e) {
            // e.printStackTrace();
            // 如果throw java.text.ParseException或者NullPointerException，就说明格式不对
            convertSuccess=false;
        }
        return convertSuccess;
    }




    public static String excelDaysToDate(int excelDays) {
        // Excel 基准日：1900-01-01（实际为 1900-01-00，但 POI 已修正此问题）
        int year = 1900;
        int month = 1;
        int day = 1;

        // 总天数 = excelDays - 1（因为基准日是 1）
        int totalDays = excelDays - 2;

        // 计算年份
        while (true) {
            int daysInYear = isLeapYear(year) ? 366 : 365;
            if (totalDays < daysInYear) break;
            totalDays -= daysInYear;
            year++;
        }

        // 计算月份
        int[] daysInMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        if (isLeapYear(year)) daysInMonth[1] = 29; // 闰年2月29天

        while (totalDays > 0) {
            int daysInCurrentMonth = daysInMonth[month - 1];
            if (totalDays < daysInCurrentMonth) break;
            totalDays -= daysInCurrentMonth;
            month++;
        }

        // 剩余天数即为日期
        day += totalDays;

        // 格式化输出
        return String.format("%04d-%02d-%02d", year, month, day);
    }

    // 判断是否为闰年
    private static boolean isLeapYear(int year) {
        return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
    }
}
